package kr.pe.johnkim.carrotpoint.mobile.controller;

import kr.pe.johnkim.carrotpoint.mobile.domain.CarrotPointMerchant;
import kr.pe.johnkim.carrotpoint.mobile.domain.CarrotPointPoint;
import kr.pe.johnkim.carrotpoint.mobile.service.CarrotPointMerchantService;
import kr.pe.johnkim.carrotpoint.mobile.service.CarrotPointPointService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * Carrot Point 포인트 관련 controller 클래스 이다.
 *
 * @author : John_Kim <cale9797@gmail.com>
 * @date : 13. 2. 6.
 */
@Controller
@RequestMapping(value = "/carrotPointPointController")
public class CarrotPointPointController {

    // SLF4J Logging
    private Logger logger = LoggerFactory.getLogger(CarrotPointPointController.class);

    @Autowired
    private CarrotPointPointService carrotPointPointService;

    @Autowired
    private CarrotPointMerchantService carrotPointMerchantService;

    /**
     * 가맹점에 해당 사용자가 등록되어 있는지 확인 한다.
     *
     * @param carrotPointPoint
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getMemberPointExist", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public CarrotPointPoint getMemberPointExist
            (@RequestBody CarrotPointPoint carrotPointPoint) throws Exception {
        logger.info("getMemberPointExist");

        logger.info("carrotPointMemberMemberId     : {}", carrotPointPoint.getCarrotPointMemberMemberId());
        logger.info("carrotPointMerchantMerchantId : {}", carrotPointPoint.getCarrotPointMerchantMerchantId());
        logger.info("activateYn                    : {}", carrotPointPoint.getActivateYn());

        return carrotPointPointService.getMemberPointExist(carrotPointPoint);
    }

    /**
     * 가맹점에서 해당 사용자의 포인트 점수(정보)를 가져 온다.
     *
     * @param carrotPointPoint
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getMemberPointInformation", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public CarrotPointPoint getMemberPointInformation
            (@RequestBody CarrotPointPoint carrotPointPoint) throws Exception {
        logger.info("getMemberPointInformation");

        logger.info("carrotPointMemberMemberId     : {}", carrotPointPoint.getCarrotPointMemberMemberId());
        logger.info("carrotPointMerchantMerchantId : {}", carrotPointPoint.getCarrotPointMerchantMerchantId());
        logger.info("activateYn                    : {}", carrotPointPoint.getActivateYn());

        return carrotPointPointService.getMemberPointInformation(carrotPointPoint);
    }

    /**
     * 포인트를 등록 한다. 가맹점에 대한 신규 등록일 경우에 해당된다.
     *
     * @param carrotPointPoint
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/registerPoint", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public CarrotPointPoint registerPoint
            (@RequestBody CarrotPointPoint carrotPointPoint) throws Exception {
        logger.info("registerPoint");

        CarrotPointPoint result = new CarrotPointPoint();

        try {
            CarrotPointMerchant parameter = new CarrotPointMerchant();
            parameter.setMerchantId(carrotPointPoint.getCarrotPointMerchantMerchantId());
            parameter.setActivateYn(carrotPointPoint.getActivateYn());

            // 결제 금액.
            double bill = Double.parseDouble(carrotPointPoint.getBill());

            // 포인트 적용율.
            double pointRate = Double.parseDouble(carrotPointMerchantService.getMerchantInformation(parameter).getPointRate());

            // 결제 금액과 적용율로 등록 할 포인트 점수를 계산 한다.
            double doublePoint = bill / pointRate;

            // 소숫점 이하는 버린다.
            int intPoint= (int)doublePoint;

            // 포인트 포멧을 int 에서 string 으로 변환 한다.
            String point = "" + intPoint;

            carrotPointPoint.setPoint(point);

            carrotPointPointService.registerPoint(carrotPointPoint);

            /*
            Push Notification 로직 추가 예정.
             */

            result.setResult("SUCCESS");
            logger.info("success to register point.");
        } catch (Exception e) {
            result.setResult("FAIL");
            logger.error("fail to register point.");
        }

        return result;
    }

    /**
     * 사용자의 포인트를 업데이트 한다.
     *
     * 포인트 추가일 경우 결제 금액과 표인트 적용율로 포인트 점수를 계산한 뒤 기존 포인트 점수에 추가한다.
     * 포인트 차감일 경우 차감할 포인트 점수만 가져오기 때문에 기존 포인트 점수에서 입력받은 차감할 포인트 점수를 뺀다.(결제 금액 계산이 필요 없다.)
     *
     * @param carrotPointPoint
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updatePoint", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public CarrotPointPoint updatePoint
            (@RequestBody CarrotPointPoint carrotPointPoint) throws Exception {
        logger.info("updatePoint");

        CarrotPointPoint result = new CarrotPointPoint();

        try {
            // 기존 포인트 점수를 가져 온다.
            int oldPoint = Integer.parseInt(carrotPointPointService.getMemberPointInformation(carrotPointPoint).getPoint());

            if(("INCREASE").equals(carrotPointPoint.getStatus())) {
                // 포인트 추가일 경우.
                CarrotPointMerchant parameter = new CarrotPointMerchant();
                parameter.setMerchantId(carrotPointPoint.getCarrotPointMerchantMerchantId());
                parameter.setActivateYn(carrotPointPoint.getActivateYn());

                // 결제 금액.
                double bill = Double.parseDouble(carrotPointPoint.getBill());

                // 포인트 적용율.
                double pointRate = Double.parseDouble(carrotPointMerchantService.getMerchantInformation(parameter).getPointRate());

                // 결제 금액과 적용율로 등록 할 포인트 점수를 계산 한다.
                double doublePoint = bill / pointRate;

                // 소숫점 이하는 버린다.
                int intPoint= (int)doublePoint;

                int newPoint = oldPoint + intPoint;
                String point = "" + newPoint;
                carrotPointPoint.setPoint(point);

                carrotPointPointService.updatePoint(carrotPointPoint);
            } else {
                // 포인트 차감일 경우.
                int newPoint = oldPoint - Integer.parseInt(carrotPointPoint.getPoint());
                String point = "" + newPoint;
                carrotPointPoint.setPoint(point);

                carrotPointPointService.updatePoint(carrotPointPoint);
            }

            /*
            Push Notification 로직 추가 예정.
             */

            result.setResult("SUCCESS");
            logger.info("success to update point.");
        } catch (Exception e) {
            result.setResult("FAIL");
            logger.error("fail to update point.");
        }

        return result;
    }

    /**
     * 사용자의 마일리지 목록을 가져 온다.(사용자의 smart phone 에 출력 한다.)
     *
     * @param carrotPointPoint
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getMemberMerchantPointList", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public List<CarrotPointPoint> getMemberMerchantPointList
            (@RequestBody CarrotPointPoint carrotPointPoint) throws Exception {
        logger.info("getMemberMerchantPointList");

        logger.info("carrotPointMemberMemberId : {}", carrotPointPoint.getCarrotPointMemberMemberId());
        logger.info("activateYn                : {}", carrotPointPoint.getActivateYn());

        return carrotPointPointService.getMemberMerchantPointList(carrotPointPoint);
    }

    /**
     * 가맹점에 등록된 사용자의 마일리지 목록을 가져 온다.(가맹점 tablet PC/iPad 에 출력 한다.)
     *
     * @param carrotPointPoint
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/getMerchantMemberPointList", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public List<CarrotPointPoint> getMerchantMemberPointList
            (@RequestBody CarrotPointPoint carrotPointPoint) throws Exception {
        logger.info("getMerchantMemberPointList");

        logger.info("carrotPointMerchantMerchantId : {}", carrotPointPoint.getCarrotPointMerchantMerchantId());
        logger.info("activateYn                    : {}", carrotPointPoint.getActivateYn());

        return carrotPointPointService.getMerchantMemberPointList(carrotPointPoint);
    }

    /**
     * 포인트를 비활성화 한다.
     *
     * 포인트를 비활성화 하면서 해당 포인트의 로그도 같이 비활성화 하지는 않는다.
     * 포인트를 추가하거나 차감할때만 로그를 남기고 비활성화 할때는 로그를 남기지 않는다.
     *
     * @param carrotPointPoint
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateDeactivatePoint", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.OK)
    @ResponseBody
    public CarrotPointPoint updateDeactivatePoint
            (@RequestBody CarrotPointPoint carrotPointPoint) throws Exception {
        logger.info("updateDeactivatePoint");

        CarrotPointPoint result = new CarrotPointPoint();

        try {
            carrotPointPointService.updateDeactivatePoint(carrotPointPoint);
            result.setResult("SUCCESS");
            logger.info("success to update deactivate point.");
        } catch (Exception e) {
            result.setResult("FAIL");
            logger.error("fail to update deactivate point.");
        }

        return result;
    }
}
